using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using OhioState.AssetManaged;


namespace OhioState.Graphics.Proxy
{
    [Serializable()]
    public class ViewProxy : SharedAsset, IView
    {
        private Viewport _viewport = new Viewport();
        public Viewport Viewport
        {
            get { return _viewport; }
            set
            { 
                _viewport = value;
                this_ChangedEvent(_camera as IAssetManaged);
            }
        }
        private ICamera _camera = new Camera();
        public ICamera CurrentCamera
        {
            get { return _camera; }
            set
            {
                //
                // For shared objects, follow this sequence:
                //   1. rewire the notification for when the object
                //        this property points to changes.
                //   2. set the property.
                //   3. perform any internal updates.
                //   4. Implicit in step 3 would be changing this 
                //         object and notifying its subscribers.
                IAssetManaged asset = value as IAssetManaged;
                if (asset != null)
                {
                    IAssetManaged cameraAsset = _camera as IAssetManaged;
                    IAssetManagedHandler changedEvent = new IAssetManagedHandler(this_ChangedEvent);
                    this.SetPropertyEventHandling(cameraAsset, asset, changedEvent);
                    _camera = value;
                    cameraAsset.AddChangedEventHandler(this_ChangedEvent);
                    this_ChangedEvent(cameraAsset);
                }
            }
        }
        private List<ILayer> _layers = new List<ILayer>();
        public List<ILayer> Layers
        {
            get { return _layers; }
            set
            {
                _layers = value;
                FireUpdateChangedEvent(this);
            }
        }

        public ViewProxy()
            : this("")
        {
        }
        public ViewProxy(string name)
            : base(name)
        {
            initEventHandlers();
        }

        private void initEventHandlers()
        {
            //
            // Set up event handlers for add and remove items
            //
            // TODO: remove this and put the logic in the GUI.
            AssetManager.Instance.AssetAdded += new IAssetManagedHandler(assetManage_AddItemEvent);
            AssetManager.Instance.AssetRemoved += new IAssetManagedHandler(assetManage_RemoveItemEvent);
        }

        public void AddLayer(ILayer layer)
        {
            if (!_layers.Contains(layer))
            {
                _layers.Add(layer);
                IAssetManaged asset = layer as IAssetManaged;
                if (asset != null)
                {
                    IAssetManagedHandler changedEvent = new IAssetManagedHandler(this_ChangedEvent);
                    asset.AddChangedEventHandler(changedEvent);
                    this_ChangedEvent(asset);
                }
            }
        }
        public void RemoveLayer(ILayer layer)
        {
            if (_layers.Contains(layer))
            {
                _layers.Remove(layer);
                IAssetManaged asset = layer as IAssetManaged;
                if (asset != null)
                {
                    IAssetManagedHandler changedEvent = new IAssetManagedHandler(this_ChangedEvent);
                    asset.RemoveChangedEventHandler(changedEvent);
                    this_ChangedEvent(asset);
                }
            }
        }
       
        public void CompositeLayers(OhioState.Graphics.IRenderPanel panel)
        {
        }

        private void this_ChangedEvent(IAssetManaged obj)
        {
            FireUpdateChangedEvent(this);
        }


        // TODO: remove this and put the logic in the GUI.
        public void assetManage_AddItemEvent(IAssetManaged obj)
        {
            if (obj is ILayer)
            {
                AddLayer((ILayer)obj);
            }

        }

        // TODO: remove this and put the logic in the GUI.
        public void assetManage_RemoveItemEvent(IAssetManaged obj)
        {
            if (obj is ILayer)
            {
                RemoveLayer((ILayer)obj);
            }
        }
        public override void ReaquireAssets()
        {
            //
            // Use the Properties to ensure the old event handlers are removed and new
            //    ones are added. Particularly if we are setting an item to itself.
            //
            //debug
            IAssetManaged asset = _camera as IAssetManaged;
            IAssetManaged item = AssetManager.Instance.Find(asset.GetType(), asset.Name);
            if (asset != null)
            {
                if (item != asset)
                {
                    this.CurrentCamera = item as ICamera;
                }
            }
            item = null;
            foreach (ILayer layer in _layers)
            {
                asset = layer as IAssetManaged;
                if (asset != null)
                {
                    item = AssetManager.Instance.Find(layer.GetType(), asset.Name);
                    if (item != layer)
                    {
                        this.RemoveLayer(layer);
                        this.AddLayer(item as ILayer);
                    }
                }
            }
        }
        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            IAssetManagedHandler changedEvent = new IAssetManagedHandler(this_ChangedEvent);
            IAssetManaged asset = _camera as IAssetManaged;
            if (asset != null)
                asset.AddChangedEventHandler(changedEvent);
            foreach (ILayer layer in _layers)
            {
                asset = layer as IAssetManaged;
                if (asset != null)
                {
                    asset.AddChangedEventHandler(changedEvent);
                }
            }
            // TODO: remove this.
            AssetManager.Instance.AssetAdded += new IAssetManagedHandler(assetManage_AddItemEvent);
            AssetManager.Instance.AssetRemoved += new IAssetManagedHandler(assetManage_RemoveItemEvent);
        }
    }
}
